package com.leyou.search.service.impl;

import com.leyou.client.ItemClient;
import com.leyou.common.dto.PageDTO;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.search.client.GoodsRepository;
import com.leyou.search.entity.Goods;
import com.leyou.search.service.IndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mySun
 * @create 2021-07-21 20:11
 */
@Service
@Slf4j
public class IndexServiceImpl implements IndexService {
    @Autowired
    private GoodsRepository repository;

    @Autowired
    private ItemClient itemClient;

    @Override
    public void loadData() {
        try {
            repository.deleteIndex();
        } catch (Throwable e) {
        }

        Boolean isSuccess = repository.createIndex(
                "{\n" +
                "  \"settings\": {\n" +
                "    \"analysis\": {\n" +
                "      \"analyzer\": {\n" +
                "        \"my_pinyin\": {\n" +
                "          \"tokenizer\": \"ik_smart\",\n" +
                "          \"filter\": [\n" +
                "            \"py\"\n" +
                "          ]\n" +
                "        }\n" +
                "      },\n" +
                "      \"filter\": {\n" +
                "        \"py\": {\n" +
                "\t\t  \"type\": \"pinyin\",\n" +
                "          \"keep_full_pinyin\": true,\n" +
                "          \"keep_joined_full_pinyin\": true,\n" +
                "          \"keep_original\": true,\n" +
                "          \"limit_first_letter_length\": 16,\n" +
                "          \"remove_duplicated_term\": true\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  },\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"id\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"suggestion\": {\n" +
                "        \"type\": \"completion\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"title\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"image\":{\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"updateTime\":{\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"specs\":{\n" +
                "        \"type\": \"nested\",\n" +
                "        \"properties\": {\n" +
                "          \"name\":{\"type\": \"keyword\" },\n" +
                "          \"value\":{\"type\": \"keyword\" }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}");
        log.info("索引库创建是否成功: {}",isSuccess);

        //加载所有数据到索引库中
        Long page = 1L;
        while (true) {
            PageDTO<SpuDTO> pageDTO = itemClient.pageSpu(page++, 50L, null, null, null, null);
            //如果值为空则结束循环
            if(pageDTO == null || CollectionUtils.isEmpty(pageDTO.getItems())){
                break;
            }
            //添加数据
            List<Goods> goodsList = pageDTO.getItems()
                    .stream()
                    .map(this::buildGoods)
                    .collect(Collectors.toList());

            repository.saveAll(goodsList);

            //如果当前页大于总页数,则结束循环
            if(page > pageDTO.getTotalPage()){
                break;
            }

        }
    }

    @Override
    public void saveGoods(Long spuId) {
        if(spuId != null){
            PageDTO<SpuDTO> pageDTO = itemClient.pageSpu(1L, 1L, null, null, spuId, null);
            SpuDTO spuDTO = pageDTO.getItems().get(0);
            Goods goods = buildGoods(spuDTO);
            repository.save(goods);
        }
    }

    @Override
    public void deleteGoods(Long spuId) {
        repository.deleteById(spuId);
    }

    private Goods buildGoods(SpuDTO spuDTO){
        Goods goods = new Goods();
        BeanUtils.copyProperties(spuDTO,goods);
        //"categoryId" : null,
        goods.setCategoryId(spuDTO.getCid3());
        //"updateTime" : null
        goods.setUpdateTime(new Date());

        //"suggestion" : null,
        // 1.品牌 2.分类 3.商品名称 4.品牌+分类 5.分类+品牌
        String s1 = StringUtils.substringBefore(spuDTO.getBrandName(),"（");
        String s2 = StringUtils.substringAfterLast(spuDTO.getCategoryName(),"/");
        String s3 = spuDTO.getName();
        String s4 = s1 + s2;
        String s5 = s2 + s1;
        goods.setSuggestion(Arrays.asList(s1,s2,s3,s4,s5));

        //"prices" : null,
        //"sold" : null,
        List<SkuDTO> skuDTOList = this.itemClient.listSkuBySid(spuDTO.getId());
        Set<Long> set = new HashSet<>();
        Long sold = 0L;
        for (SkuDTO skuDTO : skuDTOList) {
            sold += skuDTO.getSold();
            Long price = skuDTO.getPrice();
            set.add(price);
        }

        goods.setPrices(set);
        goods.setSold(sold);
        //"image" : null,
        //选取sku集合中的第一个sku的图片信息
        String images = skuDTOList.get(0).getImages();
        //截取图片的第一个
        String image = StringUtils.substringBefore(images, ",");
        goods.setImage(image);

        //"specs" : null,
        //根据sid和searching查询所有规格参数和值
        List<SpecParamDTO> specParamDTOS = this.itemClient.querySpecsValues(spuDTO.getId(), true);
        List<Map<String, Object>> specs = new ArrayList<>();

        for (SpecParamDTO specParamDTO : specParamDTOS) {
            HashMap<String, Object> map = new HashMap<>();
            //key为spec的name,值为规格对应的value(value经过处理后,如果满足条件则为区间)
//            map.put(specParamDTO.getName(),chooseSegment(specParamDTO));
            map.put("name",specParamDTO.getName());
            map.put("value",chooseSegment(specParamDTO));
            specs.add(map);
        }

        goods.setSpecs(specs);

        return goods;
    }

    private Object chooseSegment(SpecParamDTO p) {
        Object value = p.getValue();
        //value为空
        if (value == null || StringUtils.isBlank(value.toString())) {
            return "其它";
        }
        //不是数字类型 或segments属性为空 或value是一个集合,则将value直接返回
        if (!p.getNumeric() || StringUtils.isBlank(p.getSegments()) || value instanceof Collection) {
            return value;
        }
        double val = parseDouble(value.toString());
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = parseDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = parseDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    private double parseDouble(String str) {
        try {
            return Double.parseDouble(str);
        } catch (Exception e) {
            return 0;
        }
    }




}
